home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / relay / hdrmunge.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-23  |  8.5 KB  |  297 lines

  1. /*
  2.  * Usenet header modification & generation
  3.  *
  4.  * Ideally, headers should never be modified; message text, including
  5.  * headers, should be passed untouched.  Path: and Xref: demand that this
  6.  * rule be violated, and we delete huge obsolete headers to save space.
  7.  *
  8.  * Delete obsolete & large headers and Xref (can't be right),
  9.  * as headers are read.
  10.  * Recognise Newsgroups: and if more than one group, generate Xref: &
  11.  * leave holes for the article numbers - fileart will fill them in.
  12.  * (Make rn look in history instead?)
  13.  *
  14.  * Pile up headers into a static buffer until end of buffer (i.e. next
  15.  * line might not fit) [checked in hdrsave()], end of headers, end of
  16.  * file, or byte count is exhausted [checked in cparttofp].  Then write
  17.  * them to disk.  Prepend hostname! to Path: value, during output.
  18.  */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <sys/types.h>
  23. #include "libc.h"
  24. #include "news.h"
  25. #include "case.h"
  26. #include "fileart.h"
  27. #include "headers.h"
  28. #include "article.h"
  29. #include "hdrint.h"
  30. #include "msgs.h"
  31.  
  32. /*
  33.  * HDRMEMSIZ is the length of a header-stashing buffer, which is used
  34.  * only during article-header copying.
  35.  * HDRMEMSIZ can be too small if memory is tight & will only hurt performance.
  36.  * Derivation: 630 bytes is a large header (after discarding *-Version:, etc.).
  37.  */
  38. #ifndef HDRMEMSIZ
  39. #ifdef SMALLMEM
  40. #define HDRMEMSIZ 630
  41. #else
  42. #define HDRMEMSIZ 8192            /* # bytes for saving headers in core */
  43. #endif    /* SMALLMEM */
  44. #endif    /* HDRMEMSIZ */
  45.  
  46. /* private */
  47. static char **hptrs = NULL;    /* saved-headers-ptrs array; allocated once */
  48.  
  49. /* forwards */
  50. FORWARD void emithdr(), hdrsave();
  51.  
  52. /*
  53.  * Generate an Xref: header from art->a_files.
  54.  * Turn slashes in art->a_files into colons in Xref:.
  55.  */
  56. void
  57. emitxref(art)
  58. register struct article *art;
  59. {
  60.     register char *slashp, *xrefs;
  61.  
  62.     if (!art->a_xref) {
  63.         art->a_xref = YES;
  64.         xrefs = strsave(art->a_files);
  65.         for (slashp = xrefs; (slashp = strchr(slashp, FNDELIM)) != NULL; )
  66.             *slashp++ = ':';
  67.         if (fprintf(art->a_artf, "%s %s %s\n",
  68.             xrefhdr.hdrnm, hostname(), xrefs) == EOF)
  69.             fulldisk(art, spoolnm(art));
  70.         free(xrefs);
  71.     }
  72. }
  73.  
  74. /*
  75.  * --- header copying starts here ---
  76.  */
  77.  
  78. /*
  79.  * Copy headers and delete or modify a few.  Assumes hdrparse has been called.
  80.  * Delete obsolete & large headers and Xref.
  81.  * Pile up other headers for later output (Path: is changed during output).
  82.  *
  83.  * art->a_artf may be NULL, and may get set by hdrsave.
  84.  */
  85. STATIC void
  86. hdrmunge(art, buffer, hdrlen, hdrlst)
  87. register struct article *art;
  88. register char *buffer;
  89. int hdrlen;            /* optimisation only */
  90. hdrlist hdrlst;            /* headers of negative utility: snuff 'em */
  91. {
  92.     register struct hdrdef **vhp;
  93.  
  94.     if (headdebug)
  95.         (void) fputs(buffer, stderr);
  96.     for (vhp = hdrlst; *vhp != NULL; vhp++) {
  97.         register char *hdrnm = (*vhp)->hdrnm;
  98.  
  99.         if (CISTREQN(buffer, hdrnm, (int)(*vhp)->hdrlen))
  100.             return;            /* don't save this header */
  101.     }
  102.     hdrsave(art, buffer, hdrlen);
  103. }
  104.  
  105. /*
  106.  * If headers already dumped, just write to art->a_artf.
  107.  * Else if there is room, stash "hdr" away until end of headers is seen
  108.  * (could just wait until Newsgroups: and Control: are seen, if seen)
  109.  * or there is no room left in the header buffer, then open the first
  110.  * article link (on art->a_artf) and dump the saved headers and the current
  111.  * header to it.
  112.  *
  113.  * Copy into art->a_haccum (in future, could read in directly,
  114.  * iff copying is high on the profile).
  115.  *
  116.  * hdrstore is static because it is used repeatedly, it only makes sense
  117.  * to have one active at a time, and there is no memory saving in allocating
  118.  * and deallocating it, particularly since copyart's (header) buffer must
  119.  * coexist with hdrstore.
  120.  */
  121. STATIC void
  122. hdrsave(art, hdr, hdrlen)
  123. register struct article *art;
  124. char *hdr;
  125. register int hdrlen;            /* optimisation only */
  126. {
  127.     if (art->a_artf != NULL) {
  128.         emithdr(art, hdr, hdrlen);
  129.         return;
  130.     }
  131.     if (art->a_haccum == NULL) {
  132.         static char hdrstore[HDRMEMSIZ];
  133.  
  134.         art->a_haccum = hdrstore;
  135.         art->a_haccum[0] = '\0';
  136.         art->a_hnext = art->a_haccum;
  137.         art->a_hbytesleft = HDRMEMSIZ;
  138.     }
  139.     if (art->a_hbytesleft > hdrlen) {
  140.         /* add new ptr.-to-this-header to tail of saved-hdr-ptr.-list */
  141.         if (art->a_hptrs == NULL) {
  142.             art->a_hpused = 0;
  143.             art->a_hpalloced = MINSHPTRS;
  144.             if (hptrs == NULL)    /* once only */
  145.                 hptrs = (char **) nemalloc((unsigned)
  146.                     (art->a_hpalloced * sizeof(char *)));
  147.             art->a_hptrs = hptrs;
  148.         }
  149.         while (art->a_hpused >= art->a_hpalloced) {
  150.             art->a_hpalloced += MINSHPTRS;
  151.             art->a_hptrs = hptrs = (char **)
  152.                 realloc((char *)art->a_hptrs, (unsigned)
  153.                 (art->a_hpalloced * sizeof(char *)));
  154.             if (art->a_hptrs == NULL)
  155.                 errunlock("out of memory (for art->a_hptrs)", "");
  156.         }
  157.         art->a_hptrs[art->a_hpused++] = art->a_hnext;
  158.  
  159.         /* (void) strcat(art->a_haccum, hdr); */
  160.         (void) strcpy(art->a_hnext, hdr);
  161.         art->a_hnext += hdrlen;        /* points at NUL byte */
  162.         art->a_hbytesleft -= hdrlen;
  163.     } else {
  164.         hdrdump(art, NOTALLHDRS);    /* don't file */
  165.         if (art->a_artf != NULL)
  166.             emithdr(art, hdr, hdrlen);
  167.     }
  168. }
  169.  
  170. /*
  171.  * Change Path: while writing it out, just dump other headers (hdr) verbatim.
  172.  */
  173. STATIC void
  174. emithdr(art, hdr, hdrlen)
  175. register struct article *art;
  176. char *hdr;
  177. register int hdrlen;
  178. {
  179.     if (CISTREQN(hdr, pathhdr.hdrnm, (int)pathhdr.hdrlen)) {
  180.         register char *oldpath, *hostnm = hostname();
  181.  
  182.         oldpath = skipsp(&hdr[pathhdr.hdrlen]);
  183.         /*
  184.          * V7 f?printf return 0 or EOF, not a byte count, so it is
  185.          * not portable to use fprintf's return value as a byte count.
  186.          */
  187.         if (fprintf(art->a_artf, "%s %s!", pathhdr.hdrnm, hostnm) ==
  188.             EOF || fputs(oldpath, art->a_artf) == EOF)
  189.             fulldisk(art, spoolnm(art));
  190.         else {
  191.             static unsigned hostlen = 0;
  192.  
  193.             if (hostlen == 0)
  194.                 hostlen = strlen(hostnm);
  195.             art->a_charswritten += pathhdr.hdrlen + STRLEN(" ") +
  196.                 hostlen + STRLEN("!") + strlen(oldpath);
  197.         }
  198.     } else {
  199.         if (fwrite(hdr, hdrlen, 1, art->a_artf) != 1)
  200.             fulldisk(art, spoolnm(art));
  201.         else
  202.             art->a_charswritten += hdrlen;
  203.     }
  204. }
  205.  
  206. /*
  207.  * Write out saved headers after opening on art->a_artf either a temporary
  208.  * file (using mktemp(3)) or the first article link, based on art->h.h_ngs &
  209.  * nxtartnum(); set a_tmpf to which ever name is opened.
  210.  * Modify Path: value on the way.
  211.  *
  212.  * If all headers were seen, then open the first link, link to the rest,
  213.  * and generate Xref:, else open a temporary name and write the article
  214.  * there (it will get filed later by hdrdump(...,ALLHDRS) or in insart()).
  215.  */
  216. void
  217. hdrdump(art, allhdrsseen)
  218. register struct article *art;
  219. boolean allhdrsseen;        /* all headers seen & hdrdeflt() called? */
  220. {
  221.     if (art->a_filed)
  222.         return;
  223.     if (allhdrsseen)
  224.         fileart(art);            /* set a_tmpf */
  225.     else if (art->a_artf == NULL) {
  226.         nnfree(&art->a_tmpf);
  227.         art->a_tmpf = strsave(SPOOLTMP);
  228.         (void) mktemp(art->a_tmpf);
  229.         art->a_unlink = YES;
  230.         art->a_artf = fopenwclex(art->a_tmpf, "w");
  231.         if (art->a_artf == NULL)
  232.             art->a_status |= ST_DROPPED;
  233.     }
  234.     if (art->a_artf != NULL &&
  235.         art->a_haccum != NULL && art->a_haccum[0] != '\0') {
  236.         register int i;
  237.         register char **pp;
  238.         register char *nxtln;
  239.         register int saved;
  240.  
  241.         for (i = 0, pp = art->a_hptrs; i < art->a_hpused; ++i, ++pp) {
  242.             /* last in-core hdr? */
  243.             nxtln = (i >= art->a_hpused-1? art->a_hnext: pp[1]);
  244.  
  245.             saved = *nxtln;
  246.             *nxtln = '\0';
  247.             emithdr(art, *pp, nxtln - *pp);
  248.                  *nxtln = saved;            /* restore */
  249.         }
  250.         /* art->a_haccum could be freed and zeroed here, if malloced */
  251.         art->a_haccum[0] = '\0';    /* paranoia */
  252.         art->a_hnext = art->a_haccum;    /* for next article */
  253.         art->a_hpused = 0;        /* trash saved-header-ptr-list */
  254.         /* reduce saved-header-ptr-list to original size */
  255.         if (art->a_hpalloced > MINSHPTRS) {
  256.             art->a_hpalloced = MINSHPTRS;
  257.             art->a_hptrs = hptrs = (char **)
  258.                 realloc((char *)art->a_hptrs, (unsigned)
  259.                 (art->a_hpalloced * sizeof(char *)));
  260.             if (hptrs == NULL)
  261.                 errunlock("can't free a_hptrs memory", "");
  262.         }
  263.     }
  264. }
  265.  
  266. /*
  267.  * hdrparse remembers this header if it's interesting.
  268.  * hdrmunge needs art->h.h_ngs to be set, so it is called second.
  269.  * hdrmunge saves or writes this header, unless it's deemed a waste of bytes.
  270.  * hdrmunge may call hdrdump(art, NOTALLHDRS).
  271.  * hdrdump counts art->a_charswritten.
  272.  */
  273. void
  274. hdrdigest(art, line, hdrlen)
  275. register struct article *art;
  276. register char *line;
  277. int hdrlen;
  278. {
  279.     register int match;
  280.  
  281.     match = hdrparse(&art->h, line, reqdhdrs);
  282.     if (!match)
  283.         match = hdrparse(&art->h, line, opthdrs);
  284.  
  285.     /* duplicate required header and no previous refusal? */
  286.     if (match == YES+1 && !(art->a_status&ST_REFUSED)) {
  287.         register char *hdrnonl = strsave(line);
  288.  
  289.         trim(hdrnonl);
  290.         decline(art);
  291.         prefuse(art);
  292.         (void) printf("duplicate required header `%s'\n", hdrnonl);
  293.         free(hdrnonl);
  294.     }
  295.     hdrmunge(art, line, hdrlen, hdrvilest);
  296. }
  297.